
#ifndef GH_H_INCLUDED
#define GH_H_INCLUDED

#include "gh.app.h"
#include "gh.math.h"

#define GLEW_NO_GLU
#include "GL/glew.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#define NL "\n"

/* Trace Functions */
extern void ghTrace(const char *file, int line, const char *format, ...);

#if GH_APP_TRACE == 1
    #define GH_TRACE(msgStr) ghTrace(__FILE__, __LINE__, msgStr)
#else
    #define GH_TRACE(msgStr) (0)
#endif

/* Error Functions */
extern void ghErrorSetInfo(const char *file, int line, const char *format, ...);
extern const char *ghErrorGetInfo(void);

#define GH_ERROR_SET(errorStr) ghErrorSetInfo(__FILE__, __LINE__, errorStr)

/* ArcBall Functions */
extern void ghArcBallBegin(int x, int y);
extern void ghArcBallEnd(void);
extern void ghArcBallMove(int x, int y);
extern GHmat ghArcBallGetMat(void);

/* NVProgram Functions */
extern int ghNVProgramSetString(GLenum target, const char *source);

/* Time Functions */
extern double ghTimeGetSec(void);
extern double ghTimeGetMicroSec(void);
static GH_INLINE uint64_t ghTimeRdtsc(void) {
#if defined(WIN32)
    int info[4];
    __cpuid(info, 0);
    return __rdtsc();
#else
    uint32_t lo, hi;
    asm volatile ("xorl %%eax, %%eax" : : : "eax");
    asm volatile ("cpuid" : : : "eax", "ebx", "ecx", "edx");
    asm volatile ("rdtsc" : "=a" (lo), "=d" (hi));
    return (uint64_t) hi << 32 | lo;
#endif
}

#endif
